package com.yw.ffmpeg;

import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.widget.Button;

import androidx.annotation.Nullable;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * @ProjectName: AndroidFFMpeg
 * @Package: com.yw.ffmpeg
 * @ClassName: MediaMuxerActivity
 * @Description: MediaMuxer是用于将音频和视频进行混合生成多媒体文件。缺点是目前只支持一个audio track和一个video track 而且仅支持mp3输出。
 * ps:其作用是生成音频或视频文件；可以视频或音频文件混合成一个文件
 * <p>
 * 相关API介绍：
 * MediaMuxer(String path, int format)：path:输出文件的名称  format:输出文件的格式；当前只支持MP4格式；
 * addTrack(MediaFormat format)：添加通道；我们更多的是使用MediaCodec.getOutpurForma()或Extractor.getTrackFormat(int index)来获取MediaFormat;也可以自己创建；
 * start()：开始合成文件
 * writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo)：把ByteBuffer中的数据写入到在构造器设置的文件中；
 * stop()：停止合成文件
 * release()：释放资源
 * @Author: wei.yang
 * @CreateDate: 2021/5/10 16:03
 * @UpdateUser: 更新者：wei.yang
 * @UpdateDate: 2021/5/10 16:03
 * @UpdateRemark: 更新说明：
 * @Version: 1.0
 * <p>
 * 用例介绍：从MP4中提取视频并生成新的视频文件
 */
public class MediaMuxerActivity extends BaseActivity {
    private MediaExtractor mediaExtractor;
    private MediaMuxer mediaMuxer;
    private String outputPath = Environment.getExternalStorageDirectory().getPath() + "/Download/output.mp4";
    private Button btnChoicePic;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_media_muxer);
        btnChoicePic = findViewById(R.id.btnChoicePic);
        btnChoicePic.setOnClickListener(v->{
            choiceVideo();
        });
        mediaExtractor = new MediaExtractor();
        try {
            mediaMuxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void videoPathCallback(String vidoPath) {
        new Thread(){
            @Override
            public void run() {
                process(vidoPath);
            }
        }.start();
    }


    private boolean process(String videoPath) {
        try {
            mediaExtractor.setDataSource(videoPath);
            int videoTrackIndex = -1;//视频轨索引
            int frameRate = 0;//帧率
            for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
                MediaFormat mediaFormat = mediaExtractor.getTrackFormat(i);
                String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
                if (!mimeType.startsWith("video/")) {
                    continue;
                }
                frameRate = mediaFormat.getInteger(MediaFormat.KEY_FRAME_RATE);//获取帧率
                //选中当前选中的视频轨
                mediaExtractor.selectTrack(i);
                //添加编码格式,并返回一个视频轨道索引，此轨道索引就是新建的哪个输出轨道索引
                videoTrackIndex = mediaMuxer.addTrack(mediaFormat);
                //开始合成
                mediaMuxer.start();

            }

            if (mediaMuxer == null) {
                return false;
            }
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            info.presentationTimeUs = 0;
            ByteBuffer buffer = ByteBuffer.allocate(500 * 1024);//开辟一块内存用于存放视频数据
            int sampleSize = 0;
            while ((sampleSize = mediaExtractor.readSampleData(buffer, 0)) > 0) {//读取数据并将数据放到buffer中
                info.offset = 0;
                info.size = sampleSize;
                info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
                info.presentationTimeUs += 1000 * 1000 / frameRate;//单位是微秒
                mediaMuxer.writeSampleData(videoTrackIndex, buffer, info);//写入数据
                mediaExtractor.advance();//读取下一帧
            }
            //销毁谜题提取器
            mediaExtractor.release();
            //停止并销毁媒体合成器
            mediaMuxer.stop();
            mediaMuxer.release();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}
